import 'dart:async';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_base/src/model/base_model.dart';
import 'package:flutter_base/src/network/http_interceptors.dart';

/// HTTP请求方法枚举
enum HttpMethod { get, post, put, delete }

/// 网络请求客户端
class HttpApi {
  static const int connectTimeout = 35000; // 连接超时时间(接口超时时间是30秒)
  static const int receiveTimeout = 35000; // 接收超时时间
  static const int sendTimeout = 35000; // 发送超时时间

  static const String baseUrl = "https://www.kuwo.cn/openapi/"; // 正式环境
  static const String contentType = "application/json; charset=utf-8";

  late final Dio _dio;

  // 单例实现
  static final HttpApi _instance = HttpApi._internal();
  factory HttpApi() => _instance;

  HttpApi._internal() {
    _dio = Dio(
      BaseOptions(
        baseUrl: baseUrl,
        connectTimeout: const Duration(milliseconds: connectTimeout),
        receiveTimeout: const Duration(milliseconds: receiveTimeout),
        sendTimeout: const Duration(milliseconds: sendTimeout),
        contentType: contentType,
        responseType: ResponseType.json,
        validateStatus: (_) => true, // 允许所有状态码，我们将在拦截器中处理它们
      ),
    );
    _init();
  }

  void _init() {
    // 添加拦截器
    _dio.interceptors.add(HttpInterceptors());

    // 可以根据环境添加日志拦截器
    // if (true) {
    //   // Debug模式下可以改为判断环境
    //   _dio.interceptors.add(
    //     LogInterceptor(
    //       requestHeader: true,
    //       requestBody: true,
    //       responseHeader: true,
    //       responseBody: true,
    //     ),
    //   );
    // }
  }

  /// 通用请求方法
  Future<T> _request<T>({
    required HttpMethod method,
    required String url,
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(dynamic)? converter,
    String? token,
    bool rawResponse = false,
  }) async {
    Options requestOptions = options ?? Options();

    // 添加token
    if (token?.isNotEmpty == true) {
      requestOptions.headers = {...requestOptions.headers ?? {}, 'token': token};
    }

    try {
      late Response response;

      switch (method) {
        case HttpMethod.get:
          response = await _dio.get(
            url,
            queryParameters: queryParameters,
            options: requestOptions,
            cancelToken: cancelToken,
          );
          break;
        case HttpMethod.post:
          response = await _dio.post(
            url,
            data: data,
            queryParameters: queryParameters,
            options: requestOptions,
            cancelToken: cancelToken,
          );
          break;
        case HttpMethod.put:
          response = await _dio.put(
            url,
            data: data,
            queryParameters: queryParameters,
            options: requestOptions,
            cancelToken: cancelToken,
          );
          break;
        case HttpMethod.delete:
          response = await _dio.delete(
            url,
            data: data,
            queryParameters: queryParameters,
            options: requestOptions,
            cancelToken: cancelToken,
          );
          break;
      }

      // 返回原始响应
      if (rawResponse) {
        return response as T;
      }

      // 处理响应数据
      if (converter != null) {
        final responseData = BaseModel.fromJson(response.data);
        return converter(responseData.data);
      } else {
        // 默认情况下返回响应数据
        return response.data as T;
      }
    } on DioException catch (e) {
      debugPrint('请求错误: $e');
      rethrow; // 让拦截器处理异常
    } catch (e) {
      debugPrint('未知错误: $e');
      rethrow;
    }
  }

  /// GET请求 - 返回单个对象
  Future<T> get<T>(
    String url, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
  }) async {
    return _request<T>(
      method: HttpMethod.get,
      url: url,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      converter: (data) => fromJsonT(data),
    );
  }

  /// GET请求 - 返回原始响应
  Future<dynamic> getResponse(
    String url, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    return _request(
      method: HttpMethod.get,
      url: url,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
    );
  }

  /// GET请求 - 返回列表数据
  Future<List<T>> getListData<T>(
    String url, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
  }) async {
    return _request<List<T>>(
      method: HttpMethod.get,
      url: url,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      converter: (data) {
        final list = <T>[];
        if (data != null) {
          for (var item in data) {
            list.add(fromJsonT(item));
          }
        }
        return list;
      },
    );
  }

  /// POST请求 - 返回单个对象
  Future<T> post<T>(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
    String? token,
  }) async {
    return _request<T>(
      method: HttpMethod.post,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      converter: (data) => fromJsonT(data),
      token: token,
    );
  }

  /// POST请求 - 返回列表数据
  Future<List<T>> postList<T>(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
    String? token,
  }) async {
    return _request<List<T>>(
      method: HttpMethod.post,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      token: token,
      converter: (data) {
        final list = <T>[];
        if (data != null) {
          for (var item in data) {
            list.add(fromJsonT(item));
          }
        }
        return list;
      },
    );
  }

  /// POST请求 - 返回原始响应
  Future<dynamic> postResponse(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    String? token,
  }) async {
    return _request(
      method: HttpMethod.post,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      token: token,
    );
  }

  /// PUT请求 - 返回单个对象
  Future<T> put<T>(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
    String? token,
  }) async {
    return _request<T>(
      method: HttpMethod.put,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      converter: (data) => fromJsonT(data),
      token: token,
    );
  }

  /// PUT请求 - 返回原始响应
  Future<dynamic> putResponse(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    String? token,
  }) async {
    return _request(
      method: HttpMethod.put,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      token: token,
    );
  }

  /// DELETE请求 - 返回单个对象
  Future<T> delete<T>(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    required T Function(Map<String, dynamic>) fromJsonT,
    String? token,
  }) async {
    return _request<T>(
      method: HttpMethod.delete,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      converter: (data) => fromJsonT(data),
      token: token,
    );
  }

  /// DELETE请求 - 返回原始响应
  Future<dynamic> deleteResponse(
    String url, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    String? token,
  }) async {
    return _request(
      method: HttpMethod.delete,
      url: url,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken,
      token: token,
    );
  }

  /// 下载文件
  Future<Map<String, dynamic>> downloadFile(
    String url,
    String savePath, {
    dynamic data,
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? progress,
  }) async {
    Options requestOptions = options ?? Options(method: 'post');
    try {
      Response response = await _dio.download(
        url,
        savePath,
        onReceiveProgress: progress,
        cancelToken: cancelToken,
        data: data,
        options: requestOptions,
        queryParameters: params,
      );
      return {'code': response.statusCode, 'data': response.data};
    } on DioException catch (e) {
      debugPrint('下载出错----${e.toString()}');
      return {'code': -1, 'message': e.message};
    }
  }
}

// 全局单例
final httpApi = HttpApi();
